package cn.qingyun.gis.modules.baogan.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.qingyun.gis.exception.CommonException;
import cn.qingyun.gis.modules.baogan.entity.MicroStreetAuditLog;
import cn.qingyun.gis.modules.baogan.entity.MicroStreetData;
import cn.qingyun.gis.modules.baogan.entity.MicrogridCareRecordEntity;
import cn.qingyun.gis.modules.baogan.enums.*;
import cn.qingyun.gis.modules.baogan.mapper.PoiScenarioAdminMapper;
import cn.qingyun.gis.modules.baogan.service.IPoiScenarioAdminService;
import cn.qingyun.gis.modules.baogan.service.MicroStreetDataService;
import cn.qingyun.gis.modules.baogan.service.MicrogridCareRecordService;
import cn.qingyun.gis.modules.baogan.vo.PoiScenarioLikeRequest;
import cn.qingyun.gis.modules.baogan.vo.request.*;
import cn.qingyun.gis.modules.baogan.vo.response.DataResponse;
import cn.qingyun.gis.modules.baogan.vo.response.MicroGridBaseInfoVo;
import cn.qingyun.gis.modules.baogan.vo.response.ScenePersonAndTeamVo;
import cn.qingyun.gis.modules.init.system.vo.LoginUser;
import cn.qingyun.gis.modules.init.utils.SystemUtil;
import cn.qingyun.gis.modules.scenes.contant.ScenesStatus;
import cn.qingyun.gis.modules.scenes.contant.ReviewEnum;
import cn.qingyun.gis.modules.scenes.entity.PoiScenario;
import cn.qingyun.gis.modules.scenes.entity.UniAddrRegion;
import cn.qingyun.gis.modules.scenes.mapper.PoiScenarioMapper;
import cn.qingyun.gis.modules.scenes.service.IPoiScenarioService;
import cn.qingyun.gis.modules.scenes.service.UniAddrRegionService;
import com.alibaba.druid.util.StringUtils;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author guest
 * @since 2024-04-27
 */
@Slf4j
@Service
@DS("scenes_offensive")
public class PoiScenarioAdminServiceImpl extends ServiceImpl<PoiScenarioMapper, PoiScenario> implements IPoiScenarioAdminService {

    @Resource
    private UniAddrRegionService uniAddrRegionService;
    @Resource
    private MicroStreetDataService microStreetDataService;
    @Resource
    private MicrogridCareRecordService microStreetRecordService;

    @Resource
    private PoiScenarioAdminMapper poiScenarioAdminMapper;

    @Resource
    private IPoiScenarioService poiScenarioService;
    @Resource
    private MicroStreetAuditLogService microStreetAuditLogService;
    @Resource
    private MicrogridCareRecordService microgridCareRecordService;

    @Override
    public List<PoiScenario> selectPoiDateByName(PoiScenarioLikeRequest request) {
        log.debug("管理后台模糊搜索接口入参{}", request);
        //1.根据编码查询区划中心点
        QueryWrapper<UniAddrRegion> wrapper = new QueryWrapper<>();
        wrapper.select("level", "name", "code", "ST_X(center_point) AS lon", "ST_Y(center_point) AS lat")
                .eq("code", request.getCode())
                .ne("state", -1);
        UniAddrRegion uniAddrRegion = uniAddrRegionService.getBaseMapper().selectOne(wrapper);
        if (uniAddrRegion == null || uniAddrRegion.getLon() == null || uniAddrRegion.getLat() == null) {
            throw new CommonException("查询区划中心点错误");
        }
        request.setLon(uniAddrRegion.getLon());
        request.setLat(uniAddrRegion.getLat());
        //2.查询区划等级
        Integer level = uniAddrRegionService.selectLevel(request.getCode());
        request.setLevel(level);
        //3.模糊搜索
        List<PoiScenario> list = poiScenarioAdminMapper.selectPoiDataByName(request);
        log.debug("模糊搜索结果返回{}", list);
        return list;
    }

    @Override
    public List<DataResponse> selectPoiAndPolygonData(DataQueryRequest request) {
        log.debug("点面数据查询入参{}", request);
        BigDecimal rtLon = request.getRtLon();
        BigDecimal rtLat = request.getRtLat();
        BigDecimal lbLon = request.getLbLon();
        BigDecimal lbLat = request.getLbLat();
        List<String> types = request.getTypes();
        if (types.contains(ScenesStatus.BUSINESS.getDesc())) {
            types.add(ScenesStatus.COMPLEX.getDesc());
        }
        Integer level = uniAddrRegionService.selectLevel(request.getCode());
        QueryWrapper<UniAddrRegion> regionWrapper = new QueryWrapper<>();
        regionWrapper.select("id", "name", "level", "ST_AsText(wkt) AS wkt", "ST_AsText(center_point) AS centerPoint").eq("code", request.getCode()).ne("state", -1);
        UniAddrRegion uniAddrRegion = uniAddrRegionService.getBaseMapper().selectOne(regionWrapper);
        if (uniAddrRegion == null || StringUtils.isEmpty(uniAddrRegion.getWkt())) {
            throw new CommonException("未查询到该码的面数据！");
        }
        List<DataResponse> list = Lists.newArrayList();
        //1.基础数据查询
        List<DataResponse> dataResponses = poiScenarioService.selectPoiData(request, level);
        list.addAll(dataResponses);
        //2.路网+自己画的面
        QueryWrapper<MicroStreetData> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "name", "ST_AsText(wkt) AS wkt", "ST_X(ST_Centroid(wkt)) as lng", "ST_Y(ST_Centroid(wkt)) as lat", "type", "protract_flag","micro_grid_code","micro_grid_name").apply(String.format("ST_Intersects(ST_SetSRID(wkt,4326),ST_GeomFromText('MULTIPOLYGON(((%s %s,%s %s,%s %s,%s %s,%s %s)))',4326))",
                lbLon, lbLat, lbLon, rtLat, rtLon, rtLat, rtLon, lbLat, lbLon, lbLat)).apply(String.format("ST_Intersects(ST_SetSRID(wkt,4326),ST_GeomFromText('%s',4326))", uniAddrRegion.getWkt())).in("type",types);
        List<MicroStreetData> microStreetData = microStreetDataService.getBaseMapper().selectList(queryWrapper);
        microStreetData.forEach(microStreet -> {
            DataResponse dataResponse = new DataResponse();
            BeanUtils.copyProperties(microStreet, dataResponse);
            dataResponse.setWkt(microStreet.getWkt());
            list.add(dataResponse);
        });
        log.debug("返回的数据集合大小{}", list.size());
        return list;
    }

    @Override
    public List<DataResponse> selectPoiAndPolygonMicroData(MicroDataRequest request) {
        log.debug("查询具体微网格下的点面数据入参{}", request);
        String code = request.getMicroGridCode();
        List<String> types = request.getTypes();
        if (types.contains(ScenesStatus.BUSINESS.getDesc())) {
            types.add(ScenesStatus.COMPLEX.getDesc());
        }
        QueryWrapper<UniAddrRegion> regionWrapper = new QueryWrapper<>();
        regionWrapper.select("id", "name", "level", "ST_AsText(wkt) AS wkt", "ST_AsText(center_point) AS centerPoint").eq("code", code).ne("state", -1);
        UniAddrRegion uniAddrRegion = uniAddrRegionService.getBaseMapper().selectOne(regionWrapper);
        if (uniAddrRegion == null || StringUtils.isEmpty(uniAddrRegion.getWkt())) {
            throw new CommonException("未查询到该码的面数据！");
        }
        //找到该网格的对应地市码
        QueryWrapper<UniAddrRegion> regionCityWrapper = new QueryWrapper<>();
        regionCityWrapper.select("id", "code", "name", "level", "ST_AsText(wkt) AS wkt", "ST_AsText(center_point) AS centerPoint").eq("level", 2).ne("state", -1).apply(String.format("st_within(ST_GeomFromText('%s',4326),wkt)", uniAddrRegion.getWkt()));
        ;
        UniAddrRegion uniAddrCityRegion = uniAddrRegionService.getBaseMapper().selectOne(regionCityWrapper);
        String regionCityCode = null;
        if (uniAddrCityRegion != null) {
            regionCityCode = uniAddrCityRegion.getCode();
        }
        List<DataResponse> list = Lists.newArrayList();
        //1.基础数据查询
        List<DataResponse> dataResponses = poiScenarioService.selectPoiDataByMicroCode(code, regionCityCode, types);
        list.addAll(dataResponses);
        //2.路网+自己画的面
        QueryWrapper<MicroStreetData> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "name", "ST_AsText(wkt) AS wkt", "ST_X(ST_Centroid(wkt)) as lng", "ST_Y(ST_Centroid(wkt)) as lat", "protract_flag","type").apply(String.format("ST_Intersects(ST_SetSRID(wkt,4326),ST_GeomFromText('%s',4326))", uniAddrRegion.getWkt())).in("type", types);
        List<MicroStreetData> microStreetData = microStreetDataService.getBaseMapper().selectList(queryWrapper);
        microStreetData.forEach(microStreet -> {
            DataResponse dataResponse = new DataResponse();
            BeanUtils.copyProperties(microStreet, dataResponse);
            dataResponse.setWkt(microStreet.getWkt().toString());
            list.add(dataResponse);
        });
        log.debug("返回的数据集合大小{}", list.size());
        return list;
    }

    /**
     * 查询微网格看管划分基本信息
     *
     * @param request
     * @return
     */
    @Override
    public MicroGridBaseInfoVo selectMicroGridBaseInfo(MicroGridCodeRequest request) {
        MicroGridBaseInfoVo microGridBaseInfoVo = new MicroGridBaseInfoVo();
        LambdaQueryWrapper<PoiScenario> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(PoiScenario::getMicroGridCode, request.getCode())
                .eq(PoiScenario::getIsBuild, 1);
        int buildCount = this.count(queryWrapper);
        microGridBaseInfoVo.setBuildCount(buildCount);
        queryWrapper.clear();
        queryWrapper
                .eq(PoiScenario::getMicroGridCode, request.getCode())
                .eq(PoiScenario::getIsBuild, 0);
        int companyCount = this.count(queryWrapper);
        microGridBaseInfoVo.setCompanyCount(companyCount);
        //查询场景及所选自有人员、团队列表
        if (CollectionUtils.isNotEmpty(request.getSceneTypeList())) {
            List<ScenePersonAndTeamVo> scenePersonAndTeamVos = microStreetRecordService.listScenePersonAndTeamVo(request);
            microGridBaseInfoVo.setScenePersonAndTeamVos(scenePersonAndTeamVos);
        }
        return microGridBaseInfoVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addBoundary(PolygonRequest request) {
        log.debug("管理后台添加边界入参{}", request);
        LoginUser currentUser = SystemUtil.getCurrentUser();
        List<String> types = request.getTypes();
        //根据微网格查询网格、区县、地市编码
        int startLevel = 5; // 起始级别
        int endLevel = 2;   // 结束级别
        List<UniAddrRegion> ancestors = uniAddrRegionService.getAncestorsUpToLevel(request.getMicroGridCode(), startLevel, endLevel);
        if (CollectionUtils.isNotEmpty(types)) {

            List<Integer> sceneTypeList = types.stream().map(item->{
                return SceneTypeEnum.getCodeByDesc(item);
            }).collect(Collectors.toList());

            for (String type : types) {
                MicroStreetData data = MicroStreetData.builder()
                        .id(UUID.randomUUID().toString())
                        .name(request.getName())
                        .wkt(request.getWkt())
                        .type(type)
                        .createTime(new Date())
                        .phone(currentUser.getPhone())
                        .createBy(currentUser.getUsername())
                        .workNo(currentUser.getWorkNo())
                        .channelCode(request.getChannelCode())
                        .channelName(request.getChannelName())
                        .protractFlag(ProtractEnum.DRAW.getCode())
                        .build();
                UniAddrRegion microRegion = ancestors.get(0);
                if (microRegion != null) {
                    data.setMicroGridCode(microRegion.getCode());
                    data.setMicroGridName(microRegion.getName());
                }
                // 赋值 grid_code 和 grid_name
                UniAddrRegion gridRegion = ancestors.get(1);
                if (gridRegion != null){
                    data.setGridCode(gridRegion.getCode());
                    data.setGridName(gridRegion.getName());
                }
                // 赋值 dis_code 和 dis_name
                UniAddrRegion disRegion = ancestors.get(2);
                if (disRegion != null) {
                    data.setDisCode(disRegion.getCode());
                    data.setDisName(disRegion.getName());
                }
                // 赋值 city_code 和 city_name
                UniAddrRegion cityRegion = ancestors.get(3);
                if (cityRegion != null) {
                    data.setCityCode(cityRegion.getCode());
                    data.setCityName(cityRegion.getName());
                }
                microStreetDataService.addBoundary(data);

                //给面划分看管人
                if (CareTypeEnum.TEAM_DIRECT_SALE_PERSON.getCode().equals(request.getCareType())) {
                    //分配给团队人员
                    Assert.isTrue(CollectionUtils.isNotEmpty(request.getTeamNumberRequestList()), "团队人员不能为空");
                   //先删除待看管面中的已看管的点数据
                    microgridCareRecordService.deleteCareInfoInWkt(request.getWkt(),sceneTypeList);
                    request.getTeamNumberRequestList().forEach(item -> {
                        MicrogridCareRecordEntity microgridCareRecordEntity = new MicrogridCareRecordEntity();
                        BeanUtils.copyProperties(request, microgridCareRecordEntity);
                        microgridCareRecordEntity.setSceneType(SceneTypeEnum.getCodeByDesc(type));
                        microgridCareRecordEntity.setCareObject(CareObjectEnum.AOI.getCode());
                        microgridCareRecordEntity.setCaregiver(item.getCaregiver());
                        microgridCareRecordEntity.setStaffWorkNo(item.getStaffWorkNo());
                        microgridCareRecordEntity.setCreateBy(currentUser.getId());
                        microgridCareRecordEntity.setCreateTime(DateUtil.date());
                        microgridCareRecordEntity.setUpdateBy(currentUser.getId());
                        microgridCareRecordEntity.setUpdateTime(DateUtil.date());
                        microgridCareRecordService.save(microgridCareRecordEntity);
                    });
                } else {
                    //分配给渠道
                    Assert.isTrue(StringUtil.isNotEmpty(request.getChannelCode()) || StringUtil.isNotEmpty(request.getChannelName()),
                            "渠道编码、渠道名称-不能为空");
                    //先删除待看管面中的已看管的点数据
                    microgridCareRecordService.deleteCareInfoInWkt(request.getWkt(),sceneTypeList);
                    MicrogridCareRecordEntity microgridCareRecordEntity = new MicrogridCareRecordEntity();
                    BeanUtils.copyProperties(request, microgridCareRecordEntity);
                    microgridCareRecordEntity.setSceneType(SceneTypeEnum.getCodeByDesc(type));
                    microgridCareRecordEntity.setCareObject(CareObjectEnum.AOI.getCode());
                    microgridCareRecordEntity.setCreateBy(currentUser.getId());
                    microgridCareRecordEntity.setCreateTime(DateUtil.date());
                    microgridCareRecordEntity.setUpdateBy(currentUser.getId());
                    microgridCareRecordEntity.setUpdateTime(DateUtil.date());
                    microgridCareRecordService.save(microgridCareRecordEntity);
                }
            }
        }
    }

    @Override
    public boolean adjustBoundary(PolygonRequest request) throws ParseException {
        log.debug("管理后台调整边界入参{}", request);
        LoginUser currentUser = SystemUtil.getCurrentUser();
        MicroStreetData streetData = microStreetDataService.selectOneById(request.getId());//查询时使用st_astext函数转为wkt
        MicroStreetAuditLog record = new MicroStreetAuditLog();
//        Geometry geometry = new WKTReader().read(String.valueOf(streetData.getWkt()));
        record.setOldWkt(streetData.getWkt());
        record.setNewWkt(record.getNewWkt());
        record.setReviewState(ReviewEnum.REVIEWED.getCode());
        record.setCreateBy(currentUser.getUsername());
        record.setCreateId(currentUser.getId());
        record.setCreatePhone(currentUser.getPhone());
        return microStreetAuditLogService.adjustBoundary(record);
    }

    @Override
    public boolean deleteBoundary(String id) {
        LoginUser currentUser = SystemUtil.getCurrentUser();
        if (ObjectUtil.isNull(currentUser)){
            throw new CommonException("查询用户信息失败");
        }
        MicroStreetAuditLog record = MicroStreetAuditLog.builder()
                .operationType(OperationTypeEnum.DELETE.getCode())
                .createBy(currentUser.getUsername())
                .createTime(new Date())
                .createId(currentUser.getWorkNo())
                .build();
        return microStreetAuditLogService.save(record);
    }

    @Override
    public Boolean copyBoundary(PolygonRequest request) {
        log.debug("管理后台添加边界入参{}", request);
        LoginUser currentUser = SystemUtil.getCurrentUser();
        if (ObjectUtil.isNull(currentUser)){
            throw new CommonException("查询用户信息失败");
        }
        List<String> types = request.getTypes();
        boolean res = false;
        //根据微网格查询网格、区县、地市编码
        int startLevel = 5; // 起始级别
        int endLevel = 2;   // 结束级别
        List<UniAddrRegion> ancestors = uniAddrRegionService.getAncestorsUpToLevel(request.getMicroGridCode(), startLevel, endLevel);
        if (CollectionUtils.isNotEmpty(types)) {
            for (String type : types) {
                MicroStreetData data = MicroStreetData.builder()
                        .gridName(request.getGridName())
                        .gridCode(request.getGridCode())
                        .microGridCode(request.getMicroGridCode())
                        .microGridName(request.getMicroGridName())
                        .name(request.getName())
                        .wkt(request.getWkt())
                        .type(type)
                        .createTime(new Date())
                        .phone(currentUser.getPhone())
                        .createBy(currentUser.getUsername())
                        .workNo(currentUser.getWorkNo())
                        .channelCode(request.getChannelCode())
                        .channelName(request.getChannelName())
                        .protractFlag(ProtractEnum.DRAW.getCode())
                        .build();
                UniAddrRegion microRegion = ancestors.get(0);
                if (microRegion != null) {
                    data.setMicroGridCode(microRegion.getCode());
                    data.setMicroGridName(microRegion.getName());
                }
                // 赋值 grid_code 和 grid_name
                UniAddrRegion gridRegion = ancestors.get(1);
                if (gridRegion != null){
                    data.setGridCode(gridRegion.getCode());
                    data.setGridName(gridRegion.getName());
                }
                // 赋值 dis_code 和 dis_name
                UniAddrRegion disRegion = ancestors.get(2);
                if (disRegion != null) {
                    data.setDisCode(disRegion.getCode());
                    data.setDisName(disRegion.getName());
                }
                // 赋值 city_code 和 city_name
                UniAddrRegion cityRegion = ancestors.get(3);
                if (cityRegion != null) {
                    data.setCityCode(cityRegion.getCode());
                    data.setCityName(cityRegion.getName());
                }
                 res = microStreetDataService.saveBoundary(data);
            }
        }
        return res;
    }

    @Override
    public boolean hasInAoiAndCare(IdInAoiAndCareListRequest request) {
        return false;
    }
}
